#include "common.h"
#include "ftp.h"

pid_t *pids;
int nchild;
static void exec_getOneSite(char *oneline,char *dir);
static void sig_int(int signo);

/**
 * get file names of all ftp sites in 'sites'
 * 
 * @argv[1] - file 'sites' path
 * @argv[2] - output dir
 * @argv[3] - number of child process 
 */
int main(int argc,char *argv[]) {

	int i,j;
	int ret;
	FILE *fp_sites;
	pid_t p_rmdir;
	char buf[MAXLINE];

	if(argc != 4) {
		MSG("argc error:getNames");
		exit(EXIT_FAILURE);
	}

	if(signal(SIGINT,sig_int) == SIG_ERR) {
		MSG("signal failed:SIGINT");
		exit(EXIT_FAILURE);
	}
	
	p_rmdir = fork();
	if(p_rmdir < 0) {
		MSG("fork failed:remove getNames out dir");
		exit(EXIT_FAILURE);
	}
	else if(p_rmdir == 0) {
		execlp("rm","rm",argv[2],"-rf",NULL);
	}
	else {
		if(wait(NULL) == -1) {
			MSG("wait failed:remove getNames out dir");
			exit(EXIT_FAILURE);
		}
	}
	
	ret = mkdir(argv[2],0755);
	if(ret == -1) {
		MSG("mkdir failed:getNames out dir");
		exit(EXIT_FAILURE);
	}

	fp_sites = fopen(argv[1],"r");
	if(fp_sites == NULL) {
		MSG("fopen failed:getNames sites file");
		exit(EXIT_FAILURE);
	}


	nchild = atoi(argv[3]);
	if(nchild == 0) {
		MSG("nchild error:getNames");
		exit(EXIT_FAILURE);
	}

	pids = (pid_t*)malloc(sizeof(pid_t)*nchild);

	while(1) {
		bzero(pids,sizeof(pid_t)*nchild);
		for(i = 0; i < nchild; i++) {
			if(fgets(buf,MAXLINE,fp_sites) != NULL) {
				pids[i] = fork();
				if(pids[i] < 0) {
					MSG("fork failed:getNames one site process");
					exit(EXIT_FAILURE);
				}
				else if(pids[i] == 0) {
					//printf("%s",buf);
					//sleep(4);
					exec_getOneSite(buf,argv[2]);
					exit(0);
				}
			}
			else
				break;
		}
		for(j = 0; j < i; j++) {
			ret = waitpid(pids[j],NULL,0);
			if(ret == -1) {
				MSG("waitpid failed:getNames one site process");
				exit(EXIT_FAILURE);
			}
		}
		if(i < nchild)
			break;
	}
	
	free(pids);
	pids = 0;
	if(fclose(fp_sites) != 0) {
		MSG("fclose failed:getNames fp_sites");
		exit(EXIT_FAILURE);
	}

	run_log("getNames finished");
	exit(EXIT_SUCCESS);
}

static void exec_getOneSite(char *oneline,char *dir) {
	char ip_addr[MAXNAME];
	char port[MAXNAME];
	char username[MAXNAME];
	char password[MAXNAME];
	char oneSite_output[MAXLINE];
	int tmp_fd;

	if(sscanf(oneline,"%s %s %s %s",ip_addr,port,username,password) != 4) {
		MSG("error line from 'sites':%s",oneline);
		exit(EXIT_FAILURE);
	}

	snprintf(oneSite_output,MAXLINE,"%s/%s%s%s%s%s%s%s",
						dir,ip_addr,FILENAME_SEP,
						port,FILENAME_SEP,
						username,FILENAME_SEP,
						password);

	tmp_fd = open(oneSite_output,O_RDWR|O_CREAT|O_EXCL,0644);
	if(tmp_fd < 0) {
		run_log("duplicate site:%s %s %s %s",ip_addr,port,username,password);
		exit(EXIT_FAILURE);
	}

	if(close(tmp_fd) < 0) {
		MSG("close failed:tmp fd for sites output");
		exit(EXIT_FAILURE);
	}

	//printf("%s\n",oneSite_output);

	//printf("%s %s %s %s\n",ip_addr,port,username,password);
	//printf("password = (%s)\nstrlen(password) = %d\n",password,strlen(password));
	char *const ps_envp[] = {
		0
	};

	execle("./getOneSite","getOneSite",ip_addr,port,username,password,oneSite_output,NULL,ps_envp);

}

static void sig_int(int signo) {
	int i;

	MSG("getNames got SIGINT");
	if(pids == 0) {
		exit(EXIT_SUCCESS);
	}
	for(i = 0; i < nchild; i++) {
		if(pids[i] != 0) {
			kill(pids[i],SIGINT);
		}
	}

	while(wait(NULL) > 0)
		;

	if(errno != ECHILD) {
		MSG("wait error");
		exit(EXIT_FAILURE);
	}

	exit(EXIT_SUCCESS);
}
